package com.xia.minio.service;

import com.xia.minio.config.props.MinioProperties;
import com.xia.minio.contant.Constant;
import com.xia.minio.entity.FileItem;
import com.xia.minio.enums.FileType;
import com.xia.minio.util.FileUtil;
import com.xia.minio.util.ImageUtil;
import com.xia.minio.util.MinioUtil;
import io.minio.errors.ErrorResponseException;
import io.minio.errors.MinioException;
import io.minio.GetObjectResponse;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.List;
import java.util.Objects;

/**
 * todo 通过校验文件MD5实现重复文件秒传
 * 文件上传服务
 *
 * @author Blue
 * @date 2022/10/28
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class FileService {
    private final MinioUtil minioUtil;

    private  final MinioProperties minioProps;


    @PostConstruct
    public void init() {
        if (!minioUtil.bucketExists(minioProps.getBucketName())) {
            // 创建bucket
            minioUtil.makeBucket(minioProps.getBucketName());
            // 公开bucket
            minioUtil.setBucketPublic(minioProps.getBucketName());
        }
    }


    public String uploadFile(MultipartFile file) throws Exception {
        // 大小校验
        if (file.getSize() > Constant.MAX_FILE_SIZE) {
            throw new MinioException();
        }
        // 上传
        String fileName = minioUtil.upload(minioProps.getBucketName(), minioProps.getFilePath(), file);
        if (StringUtils.isEmpty(fileName)) {
            throw new Exception();
        }
        String url = generUrl(FileType.FILE, fileName);
        log.info("文件文件成功，用户id:{},url:{}","暂无", url);
        return url;
    }

    public String uploadImage(MultipartFile file) throws Exception {
        String name = "";
        try {
            // 大小校验
            if (file.getSize() > Constant.MAX_IMAGE_SIZE) {
                throw new Exception();
            }
            // 图片格式校验
            if (!FileUtil.isImage(file.getOriginalFilename())) {
                throw new Exception();
            }
            // 上传原图
            String fileName = minioUtil.upload(minioProps.getBucketName(), minioProps.getImagePath(), file);
            if (StringUtils.isEmpty(fileName)) {
                throw new Exception();
            }

            // 大于30K的文件需上传缩略图
            if (file.getSize() > 30 * 1024) {
                byte[] imageByte = ImageUtil.compressForScale(file.getBytes(), 30);
                fileName = minioUtil.upload(minioProps.getBucketName(), minioProps.getImagePath(), Objects.requireNonNull(file.getOriginalFilename()), imageByte, file.getContentType());
                if (StringUtils.isEmpty(fileName)) {
                    throw new Exception();
                }
            }
            name = generUrl(FileType.IMAGE, fileName);
            log.info("文件图片成功，用户id:{},url:{}", "暂无", name);
        } catch (IOException e) {
            log.error("上传图片失败，{}", e.getMessage(), e);
            throw new Exception();
        }
        return name;
    }


    public String generUrl(FileType fileTypeEnum, String fileName) {
        String url = minioProps.getDomain() + "/" + minioProps.getBucketName();
        switch (fileTypeEnum) {
            case FILE:
                url += "/" + minioProps.getFilePath() + "/";
                break;
            case IMAGE:
                url += "/" + minioProps.getImagePath() + "/";
                break;
            case VIDEO:
                url += "/" + minioProps.getVideoPath() + "/";
                break;
            default:
                break;
        }
        url += fileName;
        return url;
    }

    /**
     * 列出文件列表
     * @param path 路径前缀
     * @return 文件列表
     */
    public List<String> listFiles(String path) {
        return minioUtil.listFiles(minioProps.getBucketName(), path);
    }
    
    /**
     * 列出文件项列表（包含文件和文件夹的详细信息）
     * @param path 路径前缀
     * @return FileItem对象列表
     */
    public List<FileItem> listFileItems(String path) {
        return minioUtil.listFileItems(minioProps.getBucketName(), path);
    }

    /**
     * 列出指定类型的文件
     * @param fileType 文件类型
     * @return 文件列表
     */
    public List<String> listFilesByType(FileType fileType) {
        String path = "";
        switch (fileType) {
            case FILE:
                path = minioProps.getFilePath();
                break;
            case IMAGE:
                path = minioProps.getImagePath();
                break;
            case VIDEO:
                path = minioProps.getVideoPath();
                break;
            default:
                break;
        }
        return minioUtil.listFiles(minioProps.getBucketName(), path);
    }
    
    /**
     * 删除文件或文件夹
     * @param path 文件或文件夹路径
     * @return 删除结果
     */
    public boolean deleteFile(String path) {
        try {
            // 检查是否为文件夹
            if (path.endsWith("/")) {
                // 如果是文件夹，需要递归删除所有内容
                List<String> allObjects = minioUtil.listFilesRecursive(minioProps.getBucketName(), path);
                for (String object : allObjects) {
                    minioUtil.remove(minioProps.getBucketName(), "", object);
                }
            }
            // 删除指定的文件或文件夹
            return minioUtil.remove(minioProps.getBucketName(), "", path);
        } catch (Exception e) {
            log.error("删除文件/文件夹失败: {}", e.getMessage());
            return false;
        }
    }
    
    /**
     * 下载文件
     * @param filename 文件名（包含路径）
     * @return 文件流
     */
    public GetObjectResponse downloadFile(String filename) {
        try {
            // 直接调用MinioUtil下载文件
            return minioUtil.downloadFile(minioProps.getBucketName(), filename);
        } catch (Exception e) {
            log.error("下载文件失败: {}", e.getMessage());
            return null;
        }
    }
    
    /**
     * 创建文件夹
     * @param folderPath 文件夹路径
     * @return 创建结果
     */
    public boolean createFolder(String folderPath) {
        try {
            // 确保路径格式正确
            if (!folderPath.endsWith("/")) {
                folderPath = folderPath + "/";
            }
            
            // 调用MinioUtil创建文件夹
            return minioUtil.createFolder(minioProps.getBucketName(), folderPath);
        } catch (Exception e) {
            log.error("创建文件夹失败: {}", e.getMessage());
            return false;
        }
    }
}
